package com.adcc.loadsheet.billing.service.impl;

import com.adcc.loadsheet.billing.entity.BillingBillEntity;
import com.adcc.loadsheet.billing.entity.chargerule.BillingLadderEntity;
import com.adcc.loadsheet.billing.entity.chargerule.BillingRuleEntity;
import com.adcc.loadsheet.billing.entity.contractuser.ContractUserEntity;
import com.adcc.loadsheet.billing.entity.export.BillingStatistics;
import com.adcc.loadsheet.billing.entity.export.ExcelItem;
import com.adcc.loadsheet.billing.service.BillingStatisticsService;
import com.adcc.loadsheet.billing.service.ChargeBillService;
import com.adcc.loadsheet.billing.util.DateTimeUtil;
import com.adcc.loadsheet.billing.util.ExcelUtil;
import com.adcc.loadsheet.billing.vo.chargebill.ChargeBillVO;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.text.DecimalFormat;
import java.util.List;
import java.util.Map;

/**
 * 计费统计Service实现类
 * Created by zhaoml on 2020/5/19.
 */
@Service
public class BillingStatisticsServiceImpl extends BasisServiceImpl implements BillingStatisticsService {

    @Autowired
    ChargeBillService chargeBillService;

    //页面统计
    public Map<String,Object> statistics(String endMonth,List<ContractUserEntity> contractUserList){
        return getExcelItem(endMonth,contractUserList);
    }

    //导出明细excel
    public String checkExcel(String endMonth){
        String res = "";
        List<ContractUserEntity> contractUserList = contractUserEntityMapper.select(null);
        Map<String,Object> statisticsMap = getExcelItem(endMonth,contractUserList);
        List<ExcelItem> excelItems = (List<ExcelItem>)statisticsMap.get("excelItems");
        if(excelItems == null || excelItems.size() == 0){
            res = statisticsMap.get("errorStr").toString();
        }

        return res;
    }

    //导出明细excel
    public void excel(String endMonth,HttpServletResponse response){
        // 合同用户关联的普通用户（并授权此功能菜单）可以查询当前合同的用户的舱单计费统计账单，管理员可以查询全部合同用户的计费统计账单
        List<ContractUserEntity> contractUserList = contractUserEntityMapper.select(null);
        Map<String,Object> statisticsMap = getExcelItem(endMonth,contractUserList);
        List<ExcelItem> excelItems = (List<ExcelItem>)statisticsMap.get("excelItems");
        ExcelUtil.returnClient(response, "计费统计表.xls", ExcelUtil.getHSSFWorkbook(excelItems));
    }

    private Map<String,Object> getExcelItem(String endMonth,List<ContractUserEntity> contractUserList){
        Map<String,Object> resMap = Maps.newConcurrentMap();
        //获取年度1月份到当前月份（标题），第一列标题为空
        List<String> months = DateTimeUtil.getBetweenMonths(DateTimeUtil.getYear(endMonth) + "-01",endMonth);
        String[] titles = new String[months.size() + 2];
        titles[0] = ""; //第一列
        for(int i = 0;i < months.size();i ++){
            titles[i+1] = months.get(i);
        }
        titles[months.size() + 1] = "小计"; //最后一列“小计”

        List<ExcelItem> excelItems = Lists.newArrayList();
        ExcelItem excelItem = null;

        //统计
        String startDate = months.get(0) + "-01";
        String endDate = DateTimeUtil.getLastDay(endMonth + "-01");
        List<BillingStatistics> statisticsList = scUpDataEntityMapper.statistics(startDate,endDate,contractUserList);

        //先对结果进行分类
        Map<Integer, List<BillingStatistics>> maps = Maps.newConcurrentMap();
        List<BillingStatistics> statisticsList1 = null;
        for(BillingStatistics statistics : statisticsList) {
            Integer key = statistics.getContractUserId();
            if(maps.containsKey(key)) {
                //map中存在以此id作为的key，将数据存放当前key的map中
                maps.get(key).add(statistics);
            } else {
                //map中不存在以此id作为的key，新建key用来存放数据
                statisticsList1 = Lists.newArrayList();
                statisticsList1.add(statistics);
                maps.put(key, statisticsList1);
            }
        }

        List<BillingLadderEntity> billingLadderEntityList = null;       //计费阶梯
        BillingRuleEntity billingRuleEntity = null;                     //计费规则
        ChargeBillVO chargeBillVO = null;
        String[][] values = null;   //内容
        boolean flag = true;
        //循环合同用户
        for(ContractUserEntity contractUser : contractUserList) {
            flag = true;
            excelItem = new ExcelItem();
            excelItem.setTitle(contractUser.getUserAbbrev() + "集配系统发送数量和费用统计表");
            excelItem.setRemark("年份：" + DateTimeUtil.getYear(endMonth));
            excelItem.setSheetName(contractUser.getUserAbbrev());
            excelItem.setTitles(titles);
            billingRuleEntity=billingRuleEntityMapper.selectByPrimaryKey(contractUser.getBillingRuleId());
            //第一列
            values = new String[10][titles.length];
            values[0][0] = "当月服务舱单航班总数";
            values[1][0] = "当月服务旅客名单航班总数";
            values[2][0] = "当月重发航班数";
            values[3][0] = "重发率";
            values[4][0] = "当月超出"+billingRuleEntity.getRuleRate()+"%的航班数";
            values[5][0] = "当月服务航班总数";
            values[6][0] = "当月天数";
            values[7][0] = "当月日均服务航班数";
            values[8][0] = "系统技术服务费单价";
            values[9][0] = "本月服务费用";

            //判断是否有本月的数据
            List<BillingStatistics> statisticsList2 = maps.get(contractUser.getContractUserId());
            billingLadderEntityList = billingLadderEntityMapper.selectByBillingRuleId(contractUser.getBillingRuleId());
            //循环标题，避开第一列和最后一列
            for (int index = 1; index < titles.length-1; index++) {
                String costStr = "¥ 0.00";  //执行价格
                String unitPrice = "0.00";  //执行单价
                String total = "0";  //当月服务航班总数
                if(statisticsList2 != null && statisticsList2.size() > 0){
                    for (BillingStatistics statistics : statisticsList2){
                        if(!titles[index].equals(statistics.getMon())){  //不相同，说明没有本月数据，填充数据，进入下一次循环
                            flag = true;
                            continue;
                        }
                        String monStartDate = statistics.getMon() + "-01";
                        String monEndDate = DateTimeUtil.getLastDay(monStartDate);
                        chargeBillVO = chargeBillService.getChargeBill(statistics.getLoadsheetNum(),statistics.getPassgerListNum(),statistics.getRepeatNum(),billingRuleEntity.getRuleRate(),
                                monStartDate, monEndDate,contractUser,billingLadderEntityList);

                        //“日均舱单数超出当前用户计费阶梯范围，无法计价！”，不再生成帐单；（取最后一个计费阶梯）
                        if(billingLadderEntityList != null && billingLadderEntityList.size() > 0){
                            BillingLadderEntity lastLadderEntity = billingLadderEntityList.get(billingLadderEntityList.size() - 1);
                            if(chargeBillVO.getAverage() > lastLadderEntity.getLadderEndnumber()){
                                resMap.put("errorStr",contractUser.getUserAbbrev() + "日均舱单数超出当前用户计费阶梯范围，无法计价！");
                                return resMap;
                            }
                        }else{
                            resMap.put("errorStr",contractUser.getUserAbbrev() + "日均舱单数超出当前用户计费阶梯范围，无法计价！");
                            return resMap;
                        }

                        values[0][index] = chargeBillVO.getLoadsheetnum();
                        values[1][index] = chargeBillVO.getPassgerlistnum();
                        values[2][index] = chargeBillVO.getRepeatnum();
                        values[3][index] = chargeBillVO.getRepeatrate();
                        values[4][index] = chargeBillVO.getOvernum();
                        values[5][index] = chargeBillVO.getTotal();
                        values[6][index] = chargeBillVO.getDays();
                        values[7][index] = chargeBillVO.getAverage().toString();
//                        values[8][index] = chargeBillVO.getUnitPrice();
//                        values[9][index] = chargeBillVO.getCost();
                        total = chargeBillVO.getTotal();
                        unitPrice = chargeBillVO.getUnitPrice();
                        costStr = chargeBillVO.getCost();
                        flag = false;
                        break;  //查到数据，不再继续循环
                    }
                }
                if(flag){
                    String dateStr = titles[index] + "-01";
                    values[0][index] = "0";
                    values[1][index] = "0";
                    values[2][index] = "0";
                    values[3][index] = "0%";
                    values[4][index] = "0";
                    values[5][index] = "0";
                    values[6][index] = DateTimeUtil.getBetweenDate(dateStr,DateTimeUtil.getLastDay(dateStr)) + 1 + "";
                    values[7][index] = "0";
//                    values[8][index] = "0.00";
//                    values[9][index] = "¥ 0.00";
                }

                //计费统计功能中的金额提取计费帐单查询中管理员维护的实际执行金额，即手工修改的金额
                Map<String, Object> map = Maps.newHashMap();
                map.put("billingCycle", titles[index]);
                map.put("contractUserId", contractUser.getContractUserId());
                List<BillingBillEntity> billingBillEntityList = billingBillEntityMapper.select(map);
                if(billingBillEntityList != null && billingBillEntityList.size() > 0 && billingBillEntityList.get(0).getExecuteAmount() != null){
                    costStr = "¥ " + billingBillEntityList.get(0).getExecuteAmount().toString();
                    String cost = billingBillEntityList.get(0).getExecuteAmount().toString();
                    DecimalFormat df = new DecimalFormat("0.00");
                    unitPrice = "0".equals(total) ? "0.00" : df.format(Double.valueOf(cost) / Integer.valueOf(total));
                }
                values[8][index] = unitPrice;
                values[9][index] = costStr;
            }

            //横向循环，计算小计（避开第一列和最后一列）
            DecimalFormat df = new DecimalFormat("0.00");
            for(int i = 0; i < values.length; i++){
                if(i == 3 || i == 6 || i == 7 || i == 8){
                    values[i][titles.length-1] = "/";
                }else if(i == 9){
                    Double num = 0.00;
                    for(int j = 1; j < values[i].length-1; j++){
                        if(!"¥ 0.00".equals(values[i][j]) && !Strings.isNullOrEmpty(values[i][j])){
                            String value = values[i][j];
                            num += Double.valueOf(value.substring(value.indexOf("¥ ")+2));
                        }
                    }
                    values[i][titles.length-1] = "¥ " + df.format(num);;
                }else{
                    Integer num = 0;
                    for(int j = 1; j < values[i].length-1; j++){
                        String value = Strings.isNullOrEmpty(values[i][j]) ? "0" : values[i][j];
                        num += Integer.valueOf(value);
                    }
                    values[i][titles.length-1] = num.toString();
                }
            }
            excelItem.setValues(values);
            excelItems.add(excelItem);
        }
        resMap.put("excelItems",excelItems);
        return resMap;
    }
}